package com.chezai.client.global;

import android.Manifest;
import android.bluetooth.BluetoothSocket;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
import android.os.Handler;
import android.support.multidex.MultiDexApplication;
import android.support.v4.app.ActivityCompat;
import android.text.TextUtils;
import android.util.Log;

import com.chezai.client.dao.manager.TerminalParameterDaoManager;
import com.chezai.client.face.APIService;
import com.chezai.client.global.location.LocationMgr;
import com.chezai.client.server.TerminalSocketClientManager;
import com.chezai.client.server.TerminalSocketClientManager_8001;
import com.chezai.client.server.UploadGnssService;
import com.chezai.client.server.util.DeviceParameterUtil;
import com.chezai.client.utils.FileUtil;
import com.chezai.client.utils.PreferenceManager;
import com.chezai.client.utils.SpeechUtils;
import com.chezai.client.utils.Util;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechUtility;
import com.jx.driving.request.domain.LocationAttachement;
import com.obd.commands.SpeedObdCommand;
import com.obd.commands.engine.EngineRPMObdCommand;
import com.obd.commands.enums.AvailableCommandNames;
import com.obd.commands.fuel.FuelLevelObdCommand;
import com.obd.commands.io.IPostListener;
import com.obd.commands.io.ObdCommandJob;
import com.obd.commands.io.ObdGatewayService;
import com.obd.commands.io.ObdGatewayServiceConnection;
import com.orhanobut.logger.AndroidLogAdapter;
import com.orhanobut.logger.FormatStrategy;
import com.orhanobut.logger.Logger;
import com.orhanobut.logger.PrettyFormatStrategy;
import com.umeng.analytics.AnalyticsConfig;
import com.umeng.analytics.MobclickAgent;

import org.xutils.x;

import java.io.File;
import java.io.IOException;
import java.security.InvalidParameterException;
import java.util.List;

import android_serialport_api.SerialPort;

/**
 * 车载终端
 * Created by likunyang on 2017/8/24.
 */

public class TerminalApplication extends MultiDexApplication implements SharedPreferences.OnSharedPreferenceChangeListener {
    public final static String DEFAULT_PATH = "/dev/ttyMT1";//"/dev/zh_dev" //R.string.default_serial_addr
    public final static int DEFAULT_BAUDRATE = 19200; //R.string.default_serial_addr
    public static TerminalApplication mContext;
    public static String channelModel;
    public static BluetoothSocket _sock = null;
    public int engine_RPM;
    public int obdCarSpeed;
    private SerialPort mSerialPort = null;
    private int fuelLevel;
    private Intent mServiceIntent = null;
    private Handler mObdHandler = new Handler();
    private ObdGatewayServiceConnection mServiceConnection = null;
    private Runnable mQueueCommands = new Runnable() {
        public void run() {
            if (mServiceConnection.isRunning())
                queueCommands();
            mObdHandler.postDelayed(mQueueCommands, 2000);
        }
    };
    private IPostListener mListener;

    public static TerminalApplication getTerminalContext() {
        return mContext;
    }

    public void startUploadGnssService() {
        Intent intent = new Intent(this, UploadGnssService.class);
        TerminalApplication.mContext.startService(intent);
    }

    public void stopUploadGnssService() {
        Intent intent = new Intent(this, UploadGnssService.class);
        TerminalApplication.mContext.stopService(intent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;
//        channelModel = AnalyticsConfig.getChannel(this);
        //harisucici
        channelModel = "QHYC_C103";
        MobclickAgent.setCatchUncaughtExceptions(true);
        SpeechUtility.createUtility(TerminalApplication.this, SpeechConstant.APPID + "=584e609d");
        initLogService();
        initLogger();
        x.Ext.init(this);
        x.Ext.setDebug(!NetConst.RELEASE_SERVER);
        if (ActivityCompat.checkSelfPermission(TerminalApplication.mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
            LocationMgr.getInstance().bestSubscribe();
            startUploadGnssService();
        }
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            FileUtil.deleteFiles();
        }
        SpeechUtils.getInstance();
        initTerminalParams();
        initTerminalSocket();
        initOdb();
        initFace();
        initShow();
    }


    /**
     * 初始化百度人脸识别
     */
    private void initFace() {
        APIService.getInstance().init(this);
    }

    private void initShow(){
        IntentFilter filter = new IntentFilter();
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(new ConnectivityChangedReceiver(), filter);
    }

    /**
     * 初始化日志服务,并关闭日志服务和定位日志
     */
    private void initLogService() {
        PreferenceManager.getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
        PreferenceManager.putBoolean(Const.SP_IS_OPEN_LOC_LOG, false);
        PreferenceManager.putBoolean(Const.SP_IS_OPEN_LOG_SERVICE, !NetConst.RELEASE_SERVER);
    }

    private void initTerminalParams() {
        TerminalParameterDaoManager parameterDaoManager = TerminalParameterDaoManager.getInstance();
        long count = parameterDaoManager.getTerminalParameterDao().count();
        if (!(count > 0)) parameterDaoManager.initTermianlParameter();
    }

    private void initTerminalSocket() {
        TerminalSocketClientManager manager = TerminalSocketClientManager.getInstance();
        TerminalSocketClientManager_8001 manager_8001 = TerminalSocketClientManager_8001.getInstance();

        boolean a = manager.isConnect();
        boolean b = manager_8001.isConnect();
        Log.e("harisucici","鸿扬:"+(b?"true":"false"));
        manager.startSendHead();
    }

    /**
     * 初始化日志输出
     */
    private void initLogger() {
        FormatStrategy formatStrategy = PrettyFormatStrategy.newBuilder()
                .showThreadInfo(true)  // (Optional) Whether to show thread info or not. Default true
                .methodCount(0)         // (Optional) How many method line to show. Default 2
                .tag("T-")   // (Optional) Global tag for every log. Default PRETTY_LOGGER
                .build();
        Logger.addLogAdapter(new AndroidLogAdapter(formatStrategy) {
            @Override
            public boolean isLoggable(int priority, String tag) {
                return !NetConst.RELEASE_SERVER;
            }
        });
    }

    public void closeBluetoothSocket() {
        try {
            if (null != _sock) {
                _sock.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void initOdb() {
        /*
         * 如果转速为0，则随机1000~1500内的数字
         */
        mListener = new IPostListener() {
            public void stateUpdate(ObdCommandJob job) {
                String cmdName = job.getCommand().getName();
                String cmdResult = job.getCommand().getFormattedResult();
                if (AvailableCommandNames.ENGINE_RPM.getValue().equals(cmdName)) {
                    if (Util.isNumeric(cmdResult)) {
                        engine_RPM = Integer.valueOf(cmdResult);
                        /*
                         * 如果转速为0，则随机1000~1500内的数字
                         */
                    }
                } else if (AvailableCommandNames.SPEED.getValue().equals(cmdName)) {
                    if (Util.isNumeric(cmdResult)) {
                        obdCarSpeed = Integer.valueOf(cmdResult);
                    }
                } else if (AvailableCommandNames.FUEL_LEVEL.getValue().equals(cmdName)) {
                    try {
                        float fuelPercentage = Float.valueOf(cmdResult);
                        if (fuelPercentage == 0) {
                            fuelLevel = 50;
                        } else {
                            float fuel = (50 * fuelPercentage) / 100;
                            fuelLevel = (int) fuel;
                        }
                    } catch (NumberFormatException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        mServiceIntent = new Intent(this, ObdGatewayService.class);
        mServiceConnection = new ObdGatewayServiceConnection();
        mServiceConnection.setServiceListener(mListener);
        bindService(mServiceIntent, mServiceConnection, Context.BIND_AUTO_CREATE);
        startLiveData();
    }

    public void startLiveData() {
        if (!mServiceConnection.isRunning()) {
            startService(mServiceIntent);
        }
        mObdHandler.post(mQueueCommands);

    }

    public void stopLiveData() {
        if (mServiceConnection.isRunning()) {
            stopService(mServiceIntent);
        }
        mObdHandler.removeCallbacks(mQueueCommands);
    }

    private void queueCommands() {
        final ObdCommandJob speed = new ObdCommandJob(new SpeedObdCommand());
        final ObdCommandJob rpm = new ObdCommandJob(new EngineRPMObdCommand());
//        final ObdCommandJob fuelLevel = new ObdCommandJob(new FuelLevelObdCommand());
        mServiceConnection.addJobToQueue(speed);
        mServiceConnection.addJobToQueue(rpm);
//        mServiceConnection.addJobToQueue(fuelLevel);
    }

    public int getEngine_RPM() {
        engine_RPM = 1000 + (int) (Math.random() * 500 + 1);
        return 1000 + (int) (Math.random() * 500 + 1);
    }

    public List<LocationAttachement> getLocationAttachement() {
        float mile = TerminalParameterDaoManager.getInstance().getTerminalParameter128();
        return new DeviceParameterUtil().buildLocationAttachement(Float.valueOf(mile / 100).longValue(), -1, -1, getEngine_RPM());
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        if (TextUtils.equals(Const.SP_IS_OPEN_LOG_SERVICE, key)) {
            boolean isOpen = PreferenceManager.getBoolean(Const.SP_IS_OPEN_LOG_SERVICE, false);
            LogService.setOpen(isOpen);
            if (isOpen) {
                LogService.getInstance(TerminalApplication.mContext);
            }
        }
        //定位日志
        if (TextUtils.equals(Const.SP_IS_OPEN_LOC_LOG, key)) {
            boolean isOpen = PreferenceManager.getBoolean(Const.SP_IS_OPEN_LOC_LOG, false);
            LocationMgr.getInstance().setOpenLocLog(isOpen);
        }
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        PreferenceManager.getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
        TerminalSocketClientManager.getInstance().close();
        TerminalSocketClientManager_8001.getInstance().close();
    }

    public SerialPort getSerialPort() throws SecurityException, IOException, InvalidParameterException {
        Logger.t("readCard").d("getSerialPort 111: " + mSerialPort);
        if (mSerialPort == null) {
            /* Open the serial port */
            mSerialPort = new SerialPort(new File(DEFAULT_PATH), DEFAULT_BAUDRATE, 0);
        }
        Logger.t("readCard").d("getSerialPort 222: " + mSerialPort);
        return mSerialPort;
    }

    public void closeSerialPort() {
        if (mSerialPort != null) {
            mSerialPort.close();
            mSerialPort = null;
        }
    }
    class ConnectivityChangedReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {

        }
    }
}
